namespace Digitalmes.Application.Mes;

/// <summary>
/// 工序信息表服务接口
/// </summary>
[ApiExplorerSettings(GroupName = "mes")]
public sealed class ProcProcessService : IDynamicWebApiService
{
    private readonly SugarRepository<ProcProcess> _thisRepository;
    private readonly SugarRepository<MdStation> _stationRepo;

    public ProcProcessService(SugarRepository<ProcProcess> thisRepository, SugarRepository<MdStation> stationRepo)
    {
        _thisRepository = thisRepository;
        _stationRepo = stationRepo;
    }

    /// <summary>
    /// 查询所有——分页
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<ProcProcessDto>> GetPagesAsync(PageParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .ToPageAsync(param.Page, param.Limit);
        return query.Adapt<PageResult<ProcProcessDto>>();
    }

    /// <summary>
    /// 按产线Id查询所有分页
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<ProcProcessDto>> GetPagesByLineIdAsync(ProcessPageParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .Where(s => s.LineId == param.LineId)
            .ToPageAsync(param.Page, param.Limit);
        return query.Adapt<PageResult<ProcProcessDto>>();
    }

    /// <summary>
    /// 根据主键查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<ProcProcessDto> GetAsync(long id)
    {
        var model = await _thisRepository.GetByIdAsync(id);
        return model.Adapt<ProcProcessDto>();
    }

    /// <summary>
    /// 产线工序树节点展示
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<List<TreeDto<string>>> TreeAsync()
    {
        var procs = await _thisRepository.AsQueryable()
            .Includes(s => s.Line)
            .Where(s => !s.IsDisabled)
            .ToListAsync();

        var group = procs.GroupBy(s => new { s.LineId, s.LineCode, s.Line?.LineName }).ToArray();
        List<TreeDto<string>> trees = new(group.Length);
        foreach (var g in group)
        {
            TreeDto<string> tree = new()
            {
                Id = g.Key.LineId,
                Label = g.Key.LineName,
                Value = g.Key.LineCode,
            };
            trees.Add(tree);

            tree.Children = [];
            foreach (var proc in g)
            {
                tree.Children.Add(new()
                {
                    Id = proc.Id,
                    Label = $"{proc.ProcCode} ({proc.ProcName})",
                    Value = proc.ProcCode,
                    Data = proc.OpCodes.FirstOrDefault(),
                    IsLeaf = true,
                    ParentId = tree.Id,
                    ParentValue = tree.Value,
                });
            }
        }

        return trees;
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<bool> AddAsync(ProcProcessDto model)
    {
        if (await _thisRepository.IsAnyAsync(s => s.ProcCode == model.ProcCode && s.LineId == model.LineId))
        {
            Oops.ThrowBah(ErrCode.E4002);
        }

        // 多个工位必须属于一条产线
        var stations = await _stationRepo.AsQueryable()
            .Includes(s => s.Line)
            .Where(s => model.OpIds.Contains(s.Id))
            .ToListAsync();
        if (stations.Select(s => s.LineId).Distinct().Count() > 1)
        {
            Oops.ThrowBah(ErrCode.E4005, "多个工位必须属于同一条产线");
        }

        var proc = model.Adapt<ProcProcess>();
        proc.LineId = stations[0].LineId;
        proc.LineCode = stations[0].Line?.LineCode;
        return await _thisRepository.InsertAsync(proc);
    }

    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<bool> ModifyAsync(ProcProcessDto model)
    {
        if (await _thisRepository.IsAnyAsync(s => s.ProcCode == model.ProcCode && s.LineId == model.LineId && s.Id != model.Id))
        {
            Oops.ThrowBah(ErrCode.E4002);
        }

        // 多个工位必须属于一条产线
        var stations = await _stationRepo.AsQueryable()
             .Includes(s => s.Line)
             .Where(s => model.OpIds.Contains(s.Id))
             .ToListAsync();
        if (stations.Select(s => s.LineId).Distinct().Count() > 1)
        {
            Oops.ThrowBah(ErrCode.E4005, "多个工位必须属于同一条产线");
        }

        var proc = model.Adapt<ProcProcess>();
        proc.LineId = stations[0].LineId;
        proc.LineCode = stations[0].Line?.LineCode;
        return await _thisRepository.UpdateAsync(proc);
    }

    /// <summary>
    /// 删除,支持批量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [HttpDelete]
    public async Task<bool> DeleteAsync([FromBody] List<long> ids) =>
        await _thisRepository.DeleteAsync(m => ids.Contains(m.Id));
}
